package com.vsu.bookstore.mvc.ui.widgets;


import org.vaadin.autoreplacefield.EuroField;
import org.vaadin.hene.expandingtextarea.ExpandingTextArea;

import com.vaadin.addon.sqlcontainer.RowId;
import com.vaadin.data.Item;
import com.vaadin.data.Validator.EmptyValueException;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.validator.NullValidator;
import com.vaadin.data.validator.StringLengthValidator;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.DefaultFieldFactory;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Button.ClickEvent;
import com.vsu.bookstore.BookstoreApplication;
import com.vsu.bookstore.mvc.model.bean.BookStoreItem;
import com.vsu.bookstore.mvc.ui.widget.fields.CustomTextField;
import com.vsu.bookstore.mvc.ui.widget.fields.UploadImageField;
import com.vsu.bookstore.util.DatabaseHelper;

@SuppressWarnings("serial")
public class ItemForm extends Form
{
  private static class CategoryCombo extends ComboBox
  {
    public CategoryCombo(final String caption)
    {
      super(caption);
      setContainerDataSource(DatabaseHelper.get().getCategoryContainer());
      setNullSelectionAllowed(false);
      setImmediate(true);
      setItemCaptionPropertyId("Title");
      setWidth("100%");
      setRequired(true);
      addValidator(new NullValidator("You must chose category!", false));
    }

    @Override
    protected void setInternalValue(Object newValue)
    {
      if (newValue instanceof Integer)
        newValue = new RowId(new Object[]{ newValue });
      super.setInternalValue(newValue);
    }
  }

  public static class ItemFormFieldFactory extends DefaultFieldFactory
  {
    @Override
    public Field createField(final Item item, final Object propertyId, final Component uiContext)
    {
      Field result = null;
      if (propertyId.equals("image"))
      {
        result = new UploadImageField();
        result.addValidator(new NullValidator("Image must be chosen", false));
      }
      if (propertyId.equals("title"))
      {
        result = new CustomTextField("Title");
        result.addValidator(new NullValidator("Title is mandatory!", false));
        final StringLengthValidator strValidator =
          new StringLengthValidator("Title must be not empty!");
        strValidator.setMinLength(3);
        result.addValidator(strValidator);
      }
      if (propertyId.equals("description"))
      {
        result = new ExpandingTextArea("Description");
        ((TextField)result).setNullRepresentation("");
        result.addValidator(new NullValidator("Description is required!", false));
        result.setWidth("100%");
      }
      if (propertyId.equals("price"))
      {
        result = new EuroField();
        result.setCaption("Price");
        result.setWidth("100%");
        result.addValidator(new NullValidator("Price is mandatory!", false));
      }
      if (propertyId.equals("categoryId") &&
          !uiContext.isReadOnly())
        return new CategoryCombo("Category");
      if (propertyId.equals("categoryTitle") &&
          uiContext.isReadOnly())
        return new CustomTextField("Category");
      if (result != null)
      {
        result.setReadOnly(uiContext.isReadOnly());
        if (!uiContext.isReadOnly())
          result.setRequired(true);
      }
      return result;
    }
  }

  private final GridLayout grid = new GridLayout();

  private final Button okButton = new OkButton();

  private final Button cancelButton = new CancelButton();

  public ItemForm()
  {
    super();
    setCaption("Create new item");
    grid.addStyleName("itemform");
    grid.setMargin(true);
    grid.setHeight("100%");
    grid.setWidth("450px");
    grid.setSpacing(true);
    grid.setColumns(2);
    grid.setRows(8);
    grid.setColumnExpandRatio(0, 0.5f);
    grid.setColumnExpandRatio(1, 1f);
    setLayout(grid);
    setSizeFull();
    setImmediate(true);
    setWriteThrough(false);
    setFormFieldFactory(new ItemFormFieldFactory());
    populateFooter(false);
  }
  @Override
  protected void attachField(final Object propertyId, final Field field)
  {
    if (propertyId.equals("image"))
    {
      grid.addComponent(field, 0, 0, 0, 4);
      return;
    }
    if (propertyId.equals("title"))
    {
      grid.addComponent(field, 1, 0);
      return;
    }
    if (propertyId.equals("description"))
    {
      grid.addComponent(field, 0, 5, 1, 7);
      return;
    }
    if (propertyId.equals("categoryId"))
    {
      grid.addComponent(field, 1, 1);
      return;
    }
    if (propertyId.equals("categoryTitle"))
    {
      grid.addComponent(field, 1, 1);
      return;
    }
    if (propertyId.equals("price"))
    {
      grid.addComponent(field, 1, 2);
      return;
    }
  }

  @Override
  public void discard() throws SourceException
  {
    setItemDataSource(null);
    super.discard();
  }

  void populateFooter(final boolean isReadOnly)
  {
    final HorizontalLayout footer = new HorizontalLayout();
    footer.setSizeUndefined();
    footer.setMargin(true);
    footer.setSpacing(true);

    okButton.addListener(new Button.ClickListener()
    {
      @SuppressWarnings("unchecked")
      public void buttonClick(final ClickEvent event)
      {
        if (!isReadOnly())
          try
          {
            commit();
            ((BookstoreApplication) getApplication()).ui().addTableItem(((BeanItem<BookStoreItem>)getItemDataSource()).getBean());
            getApplication().getMainWindow().removeWindow(getWindow());
          }
          catch(final EmptyValueException e)
          {
          }
        else
          getApplication().getMainWindow().removeWindow(getWindow());
      }
    });
    cancelButton.addListener(new Button.ClickListener()
    {
      public void buttonClick(final ClickEvent event)
      {
        discard();
        getApplication().getMainWindow().removeWindow(getWindow());
      }
    });
    footer.addComponent(okButton);
    footer.addComponent(cancelButton);
    setFooter(footer);
  }

  @Override
  public void setReadOnly(final boolean readOnly)
  {
    super.setReadOnly(readOnly);
    cancelButton.setVisible(!readOnly);
  }
}
